﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Text;
using System.Data.Objects;
using Slam.Configuration;
using Slam;
using Microsoft.SharePoint;
using System.Web;
using System.Data.EntityClient;
using SlamCms.SharePoint.Data;
using Microsoft.SharePoint.Client.Services;
using Microsoft.SharePoint.WebControls;
using SlamCms.SharePoint.Core;
using SlamCms.Configuration;
using SlamCms.Data;
using Microsoft.SharePoint.Utilities;
using SlamCms.Common;

namespace SlamCms.SharePoint.Publishing
{
    [ServiceContract(Namespace = "")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
    [BasicHttpBindingServiceMetadataExchangeEndpoint]
    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
    public class ContentService
    {
        [WebInvoke(Method = "GET",
        ResponseFormat = WebMessageFormat.Json,
        UriTemplate = "GetContent?userName={userName}&status={status}&days={days}",
        BodyStyle = WebMessageBodyStyle.Bare)]
        [OperationContract]
        public DataTablesServiceResponse GetContent(string userName, string status, int days)
        {
            int echo = int.Parse(HttpContext.Current.Request["sEcho"]);
            int displayStart = int.Parse(HttpContext.Current.Request["iDisplayStart"]);
            int displayLength = int.Parse(HttpContext.Current.Request["iDisplayLength"]);
            string source = HttpContext.Current.Request.UrlReferrer.AbsoluteUri;
            int daysBefore = days;

            var filterStatus = GetStatus(status);
            var user = GetUser(userName);
            IEnumerable<string[]> result = null;
            int totalContentItems = 0;

            if (user != null)
            {
                if (user.Groups != null)
                {
                    var groups = (from g in user.Groups where g.Edit select g).ToList();

                    if (groups != null)
                    {
                        List<Guid> siteIds = new List<Guid>();
                        foreach (SlamCms.Data.Group g in groups)
                        {
                            if (g.Sites != null)
                                siteIds.AddRange(g.Sites.Select(id => id.SiteId));
                        }

                        List<SlamCms.Data.ContentItem> preResultContent;
                        if (status == "Published")
                        {
                            preResultContent = (from item in SlamCmsContext.Data.CreateQuery().FilterStatus(filterStatus).FilterSite(siteIds).Cache(QueryCacheBehavior.NoCache).Take(100).Get()
                                                where item.ModifiedDate > DateTime.Today.AddDays((-days))
                                                orderby item.ModifiedDate descending
                                                select item).ToList();
                        }
                        else
                        {
                            preResultContent = (from item in SlamCmsContext.Data.CreateQuery().FilterStatus(filterStatus).FilterSite(siteIds).Cache(QueryCacheBehavior.NoCache).Take(100).Get()
                                                orderby item.ModifiedDate descending
                                                select item).ToList();
                        }

                        totalContentItems = preResultContent.Count();

                        var resultContent = preResultContent.Skip(displayStart).Take(displayLength).ToList();

                        string applicationFrontEndUrl = ConfigurationManager.Environment.DefaultApplication.FrontEndUrl.TrimEnd('/');
                        string frontEndParameters = !String.IsNullOrEmpty(GetFrontEndParameters(filterStatus)) ? "?" + GetFrontEndParameters(filterStatus) : String.Empty;

                        result = new List<string[]>();

                        List<string[]> tempResult = new List<string[]>();
                        foreach (SlamCms.Data.ContentItem item in resultContent)
                        {
                            string editFormUrl = "";
                            string siteUrl = "";
                            string zone = "";
                            string siteTitle = "";

                            if (item.List != null)
                            {
                                if (item.List.Site != null)
                                {
                                    if (item.List.Site.SiteCollection != null)
                                    {
                                        editFormUrl = item.List.Site.SiteCollection.ServerRelativeUrl + item.List.Site.Url + item.List.EditFormUrl + "?ID=" + item.ListRelativeId + "&Source=" + SPHttpUtility.UrlKeyValueEncode(source);
                                        siteUrl = item.List.Site.SiteCollection.ServerRelativeUrl + item.List.Site.Url;
                                    }
                                    if (item.List.Site.Zones != null)
                                    {
                                        if (item.List.Site.Zones.Count() > 0)
                                            zone = item.List.Site.Zones.FirstOrDefault().Title;
                                    }

                                    siteTitle = item.List.Site.Title;
                                }

                            }

                            tempResult.Add(new string[]{ applicationFrontEndUrl + "/link/" + item.ContentItemId.Replace("-p",String.Empty) + frontEndParameters, 
                                                    editFormUrl,
                                                     !String.IsNullOrEmpty(item.ReferenceTitle)?item.ReferenceTitle:"no title", 
                                                    siteUrl,!String.IsNullOrEmpty(zone) ? (zone+": "+siteTitle):siteTitle,
                                                    item.ContentType != null ?item.ContentType.Title : String.Empty,
                                                    item.ModifiedByUser != null ? item.ModifiedByUser.Name : String.Empty, 
                                                    item.ModifiedDate.ToShortDateString()
                        });
                        }
                        result = tempResult;
                    }
                }
            }

            return new DataTablesServiceResponse
            {
                sEcho = echo,
                iTotalRecords = totalContentItems,
                iTotalDisplayRecords = totalContentItems,
                aaData = (result != null ? result : new List<string[]>())

            };
        }

        [WebInvoke(Method = "GET",
        ResponseFormat = WebMessageFormat.Json,
        UriTemplate = "GetContentBySite?userName={userName}&status={status}&siteId={siteId}&days={days}",
        BodyStyle = WebMessageBodyStyle.Bare)]
        [OperationContract]
        public DataTablesServiceResponse GetContentBySite(string userName, string status, string siteId, int days)
        {

            int echo = int.Parse(HttpContext.Current.Request["sEcho"]);
            int displayStart = int.Parse(HttpContext.Current.Request["iDisplayStart"]);
            int displayLength = int.Parse(HttpContext.Current.Request["iDisplayLength"]);
            string source = HttpContext.Current.Request.UrlReferrer.AbsoluteUri;
            int daysBefore = days;

            var filterStatus = GetStatus(status);
            var user = GetUser(userName);
            IEnumerable<string[]> result = null;

            int totalContentItems = 0;

            if (user != null)
            {
                Guid siteGuid = new Guid(siteId);

                List<SlamCms.Data.ContentItem> preResultContent;
                if (status == "Published")
                {
                    preResultContent = (from item in SlamCmsContext.Data.CreateQuery().FilterStatus(filterStatus).FilterSite(new Guid[] { siteGuid }).Cache(QueryCacheBehavior.NoCache).Get()
                                        where item.ModifiedDate > DateTime.Today.AddDays((-days))
                                        orderby item.ModifiedDate descending
                                        select item).ToList();
                }
                else
                {
                    preResultContent = (from item in SlamCmsContext.Data.CreateQuery().FilterStatus(filterStatus).FilterSite(new Guid[] { siteGuid }).Cache(QueryCacheBehavior.NoCache).Get()
                                        orderby item.ModifiedDate descending
                                        select item).ToList();
                }

                totalContentItems = preResultContent.Count();
                var resultContent = preResultContent.Skip(displayStart).Take(displayLength).ToList();

                string applicationFrontEndUrl = ConfigurationManager.Environment.DefaultApplication.FrontEndUrl.TrimEnd('/');
                string frontEndParameters = !String.IsNullOrEmpty(GetFrontEndParameters(filterStatus)) ? "?" + GetFrontEndParameters(filterStatus) : String.Empty;

                result = new List<string[]>();

                List<string[]> tempResult = new List<string[]>();
                foreach (SlamCms.Data.ContentItem item in resultContent)
                {
                    string editFormUrl = "";

                    if (item.List != null)
                    {
                        if (item.List.Site != null)
                        {
                            if (item.List.Site.SiteCollection != null)
                            {
                                editFormUrl = item.List.Site.SiteCollection.ServerRelativeUrl + item.List.Site.Url + item.List.EditFormUrl + "?ID=" + item.ListRelativeId + "&Source=" + SPHttpUtility.UrlKeyValueEncode(source);
                            }
                        }

                    }

                    tempResult.Add(new string[]{ applicationFrontEndUrl + "/link/" + item.ContentItemId.Replace("-p",String.Empty) + frontEndParameters, 
                                                    editFormUrl,
                                                    !String.IsNullOrEmpty(item.ReferenceTitle)?item.ReferenceTitle:"no title", 
                                                    item.ContentType != null ?item.ContentType.Title : String.Empty,
                                                    item.ModifiedByUser != null ? item.ModifiedByUser.Name : String.Empty, 
                                                    item.ModifiedDate.ToShortDateString()
                        });
                }
                result = tempResult;
            }

            return new DataTablesServiceResponse
            {
                sEcho = echo,
                iTotalRecords = totalContentItems,
                iTotalDisplayRecords = totalContentItems,
                aaData = (result != null ? result : new List<string[]>())
            };
        }

        [WebInvoke(Method = "GET",
       ResponseFormat = WebMessageFormat.Json,
	   UriTemplate = "GetExpiringContent?userName={userName}&days={days}&includeExpired={includeExpiredContent}",
       BodyStyle = WebMessageBodyStyle.Bare)]
        [OperationContract]
        public DataTablesServiceResponse GetExpiringContent(string userName, int days, bool includeExpiredContent)
        {
            int echo = int.Parse(HttpContext.Current.Request["sEcho"]);
            int displayStart = int.Parse(HttpContext.Current.Request["iDisplayStart"]);
            int displayLength = int.Parse(HttpContext.Current.Request["iDisplayLength"]);
            string source = HttpContext.Current.Request.UrlReferrer.AbsoluteUri;

			string orderBy = "ExpirationDate asc";
			if (HttpContext.Current.Request["iSortCol_0"] != null)
			{
				orderBy = HttpContext.Current.Request["iSortCol_0"] == "2" ? "ReferenceTitle" : "ExpirationDate";
				if (HttpContext.Current.Request["sSortDir_0"] != null)
					orderBy += " " + HttpContext.Current.Request["sSortDir_0"];
			}

            var user = GetUser(userName);
            IEnumerable<string[]> result = null;
            int totalContentItems = 0;

			if (user != null)
			{
				if (user.Groups != null)
				{
					var groups = (from g in user.Groups where g.Edit select g).ToList();

					if (groups != null)
					{
						List<Guid> siteIds = new List<Guid>();
						foreach (SlamCms.Data.Group g in groups)
						{
							if (g.Sites != null)
								siteIds.AddRange(g.Sites.Select(id => id.SiteId));
						}

						var dateNow = DateTime.Today;
						var dateScope = dateNow.AddDays(days);

						totalContentItems = SlamCmsContext.Data.CreateQuery()
							.FilterStatus(FilterStatus.Live).Filter("ContentItem.ExpirationDate IS NOT NULL {1}and ContentItem.ExpirationDate < '{0}'".F(dateScope.ToString("MM/dd/yyyy"), !includeExpiredContent ? "and ContentItem.ExpirationDate >= '" + dateNow.ToString("MM/dd/yyyy") + "' " : ""))
												.FilterSite(siteIds)
												.Cache(QueryCacheBehavior.NoCache)
												.Count();

						var resultContent = SlamCmsContext.Data.CreateQuery()
												.FilterStatus(FilterStatus.Live).Filter("ContentItem.ExpirationDate IS NOT NULL {1}and ContentItem.ExpirationDate < '{0}'".F(dateScope.ToString("MM/dd/yyyy"), !includeExpiredContent ? "and ContentItem.ExpirationDate >= '" + dateNow.ToString("MM/dd/yyyy") + "' " : ""))
												.FilterSite(siteIds)
												.Cache(QueryCacheBehavior.NoCache)
												.OrderBy(orderBy)
												.Take(displayStart + displayLength)
												.Get()
												.Skip(displayStart);

						string applicationFrontEndUrl = ConfigurationManager.Environment.DefaultApplication.FrontEndUrl.TrimEnd('/');

						result = new List<string[]>();

						List<string[]> tempResult = new List<string[]>();
						foreach (SlamCms.Data.ContentItem item in resultContent)
						{
							string zone = "";
							string siteTitle = "";
							string siteUrl = "";

							if (item.List != null)
							{
								if (item.List.Site != null)
								{
									if (item.List.Site.Zones != null)
									{
										if (item.List.Site.Zones.Count() > 0)
											zone = item.List.Site.Zones.FirstOrDefault().Title;
									}
									siteTitle = item.List.Site.Title;
									siteUrl = item.List.Site.SiteCollection.ServerRelativeUrl + item.List.Site.Url;
								}
							}

							tempResult.Add(new string[]{ item.ExpirationDate.Value.ToShortDateString(),
                                                    item.ExpirationDate < dateNow ? true.ToString() : false.ToString(),
                                                     !String.IsNullOrEmpty(item.ReferenceTitle)?item.ReferenceTitle:"no title",
                                                     applicationFrontEndUrl + "/link/" + item.ContentItemId.Replace("-p",String.Empty),
                                                    !String.IsNullOrEmpty(zone) ? (zone + ": <a href=\"{0}\">{1}</a>".F(siteUrl, siteTitle)) : "<a href=\"{0}\">{1}</a>".F(siteUrl, siteTitle),
                                                    item.ContentType != null ?item.ContentType.Title : String.Empty,
                                                    item.CreatedByUser != null ? item.CreatedByUser.Name : String.Empty, 
                                                    item.CreatedDate.ToShortDateString()});
						}
						result = tempResult;
					}
				}
			}

            return new DataTablesServiceResponse
            {
                sEcho = echo,
                iTotalRecords = totalContentItems,
                iTotalDisplayRecords = totalContentItems,
                aaData = (result != null ? result : new List<string[]>())
            };
        }

        private string GetFrontEndParameters(SlamCms.Data.FilterStatus filterStatus)
        {
            string parameters = "";

            switch (filterStatus)
            {
                case SlamCms.Data.FilterStatus.Draft:
                    parameters = "preview=true";
                    break;
                default:
                    break;
            }

            return parameters;
        }

        private SlamCms.Data.FilterStatus GetStatus(string status)
        {
            SlamCms.Data.FilterStatus filterStatus;
            switch (status)
            {
                case "Draft":
                    filterStatus = SlamCms.Data.FilterStatus.Draft;
                    break;
                case "Published":
                    filterStatus = SlamCms.Data.FilterStatus.Live;
                    break;
                default:
                    filterStatus = SlamCms.Data.FilterStatus.None;
                    break;
            }

            return filterStatus;
        }

		private SlamCms.Data.User GetUser(string userName)
		{
			return (from u in SlamCmsContext.Data.Users
					where u.UserName.Equals(userName, StringComparison.OrdinalIgnoreCase)
					select u).FirstOrDefault();
		}
    }
}